package com.example.demo.config.velocitys;

import com.example.demo.util.CommonMap;
import com.example.demo.util.StringUtil;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <h4>功能:【代码生成启动类】【创建人：QIAOLIANG】</h4>
 *
 * @时间:2018/6/27 0027 9:54
 * @备注:<h4></h4>
 */
public class MyBatisGeneratorUtils {

    //获得url
    private final String URL = "jdbc:mysql://localhost:3306/system?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&nullCatalogMeansCurrent=true";

    //获得驱动
    private final String DRIVER = "com.mysql.jdbc.Driver";

    //数据库账号
    private final String USERNAME = "root";

    //数据库密码
    private final String PASSWORD = "root";

    //作者
    private final String AUTHOR = "QiaoLiang";


    private final String PAGE = "com.example.demo";

    //生成的文件路径
    //entity实体类
    private final String ENTITYPATH = "/java/com/example/demo/entity";

    //example
    private final String EXAMPLEPATH = "/java/com/example/demo/example";

    //service 接口
    private final String SERVICEPATH = "/java/com/example/demo/service";

    //serviceImpl 接口实现类
    private final String SERVICEIMPLPATH = "/java/com/example/demo/service/impl";

    //mapper
    private final String MAPPERPATH = "/java/com/example/demo/mapper";

    //mapper.xml
    private final String MAPPERXMLPATH = "/resources/mapping";

    //controller
    private final String CONTROLLER = "/java/com/example/demo/web/controller";


    public static void main(String[] args) {
        MyBatisGeneratorUtils velocityGenerator = new MyBatisGeneratorUtils();
        velocityGenerator.generate();
    }


    /**<h4>功能：【数据库连接】【2018/6/27 0027 10:11】【创建人：QIAOLIANG】</h4>
     * <h4></h4>
     * 
     */
    public Connection getConnection()  throws Exception  {

        Class.forName(DRIVER);

        Connection connection= DriverManager.getConnection(URL, USERNAME, PASSWORD);

        connection.setAutoCommit(true);

        return connection;
        
    }


    /**<h4>功能：【代码生成】【2018/6/27 0027 10:12】【创建人：QIAOLIANG】</h4>
     * <h4></h4>
     * 
     */
    public void generate(){

        try{

            //获取数据库的链接
            Connection connection = getConnection();

            //该方法获取一个DatabaseMetaData对象，该对象包含关于此Connection对象所连接的数据库的元数据。元数据包括关于数据库的表、受支持的SQL语法、存储过程、此连接功能等的信息。
            DatabaseMetaData databaseMetaData = connection.getMetaData();

            //获取数据库中所有的表
            String[] types = { "TABLE" };

            ResultSet rs = databaseMetaData.getTables(null, null, "%", types);

            //获取所有的表字段
            while (rs.next()) {

                //表名
                String tableName = rs.getString("TABLE_NAME");

                //表的所有字段
                ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%");

                //表的主键
                ResultSet primaryKeys = databaseMetaData.getPrimaryKeys(null,null, tableName);

                //储存所有的表字段
                List<TableClass> tableClassList = new ArrayList<>();

                //循环获取表字段并储存
                while(resultSet.next()){

                    TableClass tableClass = new TableClass();

                    //获取字段名称
                    tableClass.setFieldName(resultSet.getString("COLUMN_NAME"));
                    //获取字段类型
                    tableClass.setFieldType(resultSet.getString("TYPE_NAME"));
                    // 列名转换成Java属性名
                    String attrName = StringUtil.convertToCamelCase(tableClass.getFieldName());

                    tableClass.setAttrName(attrName);
                    tableClass.setAttrname(StringUtil.uncapitalize(attrName));

                    // 列的数据类型，转换成Java类型
                    String attrType = CommonMap.javaTypeMap.get(tableClass.getFieldType());
                    tableClass.setAttrType(attrType);

                    //字段在数据库的注释
                    tableClass.setFieldComment(resultSet.getString("REMARKS"));

                    tableClassList.add(tableClass);

                }

                //主键名称
                String pkName="";

                while(primaryKeys.next()){

                    pkName = StringUtil.uncapitalize(primaryKeys.getString("COLUMN_NAME"));

                }

                VelocityEngine ve = new VelocityEngine();

                ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");

                ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());

                ve.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");

                ve.setProperty(Velocity.INPUT_ENCODING, "UTF-8");

                ve.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");

                ve.init();

                Template entity = ve.getTemplate("gen/entity.java.vm");

                Template entityExample = ve.getTemplate("gen/example.java.vm");

                Template mapper = ve.getTemplate("gen/Mapper.java.vm");

                Template service = ve.getTemplate("gen/Service.java.vm");

                Template serviceImpl = ve.getTemplate("gen/ServiceImpl.java.vm");

                Template mapperxml = ve.getTemplate("gen/Mapper.xml.vm");

                Template controller = ve.getTemplate("gen/controller.java.vm");

                VelocityContext ctx = new VelocityContext();

                ctx.put("className", StringUtil.convertToCamelCase(tableName));

                ctx.put("classname", tableName);

                ctx.put("package", PAGE);

                ctx.put("list", tableClassList);

                ctx.put("author", AUTHOR);

                ctx.put("datetime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

                ctx.put("pkName",StringUtil.convertToCamelCase(pkName));

                ctx.put("pkname",pkName);

                String patch = System.getProperty("user.dir");

                patch = patch + "/src/main";

                merge(entity,ctx,patch + ENTITYPATH, "/"+ StringUtil.convertToCamelCase(tableName)+".java");

                merge(entityExample,ctx,patch + EXAMPLEPATH, "/" + StringUtil.convertToCamelCase(tableName)+"Example.java");

                merge(mapper,ctx,patch + MAPPERPATH, "/" + StringUtil.convertToCamelCase(tableName)+"Mapper.java");

                merge(service,ctx,patch + SERVICEPATH, "/" + StringUtil.convertToCamelCase("I"+StringUtil.convertToCamelCase(tableName))+"Manager.java");

                merge(serviceImpl,ctx,patch + SERVICEIMPLPATH, "/" + StringUtil.convertToCamelCase(tableName)+"ManagerImpl.java");

                merge(mapperxml,ctx,patch + MAPPERXMLPATH, "/" + StringUtil.convertToCamelCase(tableName)+"mapper.xml");

                merge(controller,ctx,patch + CONTROLLER, "/" + StringUtil.convertToCamelCase(tableName)+"Controller.java");

                System.out.println("数据库表："+tableName+"生成成功！");

            }

        }catch (Exception e){
            System.err.println("生成代码出现异常，"+e.getMessage());
        }

    }


    private static void merge(Template template, VelocityContext ctx,String path, String nameClass) {

        PrintWriter writer = null;

        try {

            File file =new File(path);
            path=path.replace('/', '\\'); // 将/换成\
            //如果文件夹不存在则创建

            if (!file.exists()) {

                file.mkdirs();

            }

            writer = new PrintWriter(path+nameClass);

            template.merge(ctx, writer);

            writer.flush();


        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            writer.close();

        }
    }




}